﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting;
using System.Xml;

using CommunityServer.Configuration;

using CSLive.ControlPanel;

namespace CSLive
{
    public sealed class LiveConfiguration
    {
        private static bool _enableLiveID;
        private static XmlNode LiveConfigurationNode;

        /// <summary>
        /// Generates a new instance of the Configuration Class
        /// </summary>
        /// <value>A Instance of the Configuration Class</value>
        public static LiveConfiguration Instance
        {
            get { return new LiveConfiguration(); }
        }

        /// <summary>
        /// Collection of Controls contained in CSLive
        /// </summary>
        /// <value>A Dictionary of ICSLiveControls keyed on the ICSLiveControl's Name</value>
        public Dictionary< string, ICSLiveControl > Controls
        {
            get
            {
                var a = new Dictionary< string, ICSLiveControl >();

                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                foreach ( Type t in currentAssembly.GetTypes() )
                    foreach ( Type ty in t.GetInterfaces() )
                        if ( ty == typeof ( ICSLiveControl ) )
                        {
                            ObjectHandle handle = Activator.CreateInstanceFrom( currentAssembly.Location, t.ToString() );
                            var control = ( ICSLiveControl ) handle.Unwrap();
                            a.Add( control.Name, control );
                        }
                return a;
            }
        }

        /// <summary>
        /// Collection of Controls Groups and their controls contained in CSLive
        /// </summary>
        /// <value>A Dictionary of, a Dictionaries of ICSLiveControls keyed on the ICSLiveControl's Name, keyed on the GroupName</value>
        public Dictionary< string, List< ICSLiveControl > > ControlGroups
        {
            get
            {
                var a = new Dictionary< string, List< ICSLiveControl > >();

                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                foreach ( Type t in currentAssembly.GetTypes() )
                    foreach ( Type ty in t.GetInterfaces() )
                        if ( ty == typeof ( ICSLiveControl ) )
                        {
                            ObjectHandle handle = Activator.CreateInstanceFrom( currentAssembly.Location, t.ToString() );
                            var control = ( ICSLiveControl ) handle.Unwrap();
                            if ( !a.ContainsKey( control.Group ) )
                                a.Add( control.Group, new List< ICSLiveControl >() );
                            a[ control.Group ].Add( control );
                        }
                return a;
            }
        }

        /// <summary>
        /// Example of the LiveID Xml Configuration.
        /// </summary>
        public bool EnableLiveID
        {
            get
            {
                if ( _enableLiveID == false )
                {
                    LoadConfiguration();

                    string enabled = LiveConfigurationNode.Attributes.GetNamedItem( "EnableLiveID" ).Value;
                    if ( string.IsNullOrEmpty( enabled ) )
                    {
                        throw new XmlException( "Attribute \"EnableLiveID\" is not defined on communityserver_override.config's <LiveConfiguration> node.  " );
                    }

                    _enableLiveID = bool.TrueString == LiveConfigurationNode.Attributes.GetNamedItem( "EnableLiveID" ).Value;
                }

                return _enableLiveID;
            }
        }

        /// <summary>
        /// Get Configuration Settings for a Specific CSLive Control
        /// </summary>
        /// <param name="ControlName">The Name of the Control as defined by the ICSLiveControl interface inheritance</param>
        /// <returns>An array of Config Settings as obtained from the Configuration File</returns>
        public ConfigSetting[] getConfigSettings( string ControlName )
        {
            if ( LiveConfigurationNode == null ) LoadConfiguration();
            XmlNode control = LiveConfigurationNode.SelectSingleNode( string.Format( "Controls/Control[@name='{0}']", ControlName ) );
            if ( control == null ) throw new XmlException( string.Format( "The Control ({0}) does not exist in the communityserver configuration files", ControlName ) );
            var settings = new List< ConfigSetting >();
            foreach ( XmlNode setting in control.ChildNodes )
                settings.Add( ConfigSetting.Parse( setting ) );
            return settings.ToArray();
        }

        /// <summary>
        /// Get Configuration Setting for a Specific CSLive Control
        /// </summary>
        /// <param name="SettingName">The String representation of the Setting</param>
        /// <param name="ControlName">The Name of the Control as defined by the ICSLiveControl interface inheritance</param>
        /// <returns>ConfigSetting struct.  If the config file doesn't contain a setting for the Config it will load</returns>
        public ConfigSetting getConfigSetting( string ControlName, string SettingName )
        {
            if ( LiveConfigurationNode == null ) LoadConfiguration();
            XmlNode control = LiveConfigurationNode.SelectSingleNode( string.Format( "Controls/Control[@name='{0}']", ControlName ) );
            if ( control == null ) throw new XmlException( string.Format( "The Control ({0}) does not exist in the communityserver configuration files", ControlName ) );
            XmlNode setting = control.SelectSingleNode( string.Format( "param[@name='{0}']", SettingName ) );
            if ( setting == null ) throw new XmlException( string.Format( "The setting ({0}) does not exist in the the communityserver configuration files", SettingName ) );
            return ConfigSetting.Parse( setting );
        }

        /// <summary>
        /// Saves the Configuration Setting
        /// </summary>
        /// <param name="SettingName">The String representation of the Setting</param>
        /// <param name="ControlName">The Name of the Control as defined by the ICSLiveControl interface inheritance</param>
        /// <param name="SettingValue">Object representing the Setting's Value</param>
        public void saveConfigSetting( string ControlName, string SettingName, object SettingValue )
        {
            throw new NotImplementedException( "This feature should be implemented in cs2008.1, This bug has been reported to the Community Server Product Team." );
        }

        /// <summary>
        /// Loads the Live XML node from CSConfiguration.
        /// </summary>
        private void LoadConfiguration()
        {
            if ( LiveConfigurationNode == null )
            {
                LiveConfigurationNode = CSConfiguration.GetConfig().GetConfigSection( "CommunityServer/Core/LiveConfiguration" );

                if ( LiveConfigurationNode == null )
                {
                    throw new XmlException( "<LiveConfiguration> is not defined in communityserver_override.config." );
                }
            }
        }
    }
}